﻿using System.Collections.Generic;
using UnityEngine;

namespace SnakeGame
{
    public class Snake
    {
        /// <summary>
        /// 地图二维索引的数据结构
        /// </summary>
        public struct PointIndex
        {
            public int x { get; set; }
            public int y { get; set; }
        }

        /// <summary>
        /// 蛇蛇的属性
        /// </summary>
        private GameObject nodePointRes;

        public List<NodePoint> bodyList = new List<NodePoint>();
        public Vector2 curDirection = Vector2.left;
        public PointIndex LastPointIndex;
        public Vector2 LastDirection;

        /// <summary>
        /// ctor
        /// </summary>
        /// <param name="res">组成蛇蛇身体的点的资源</param>
        public Snake(GameObject res)
        {
            nodePointRes = res;
            GnerateDefaultSnake();
        }

        /// <summary>
        /// 生成一条初始的蛇
        /// </summary>
        private void GnerateDefaultSnake()
        {
            //默认两个点的身体
            LastDirection = curDirection;
            var node1 = new NodePoint(nodePointRes);
            node1.RefreshPosition(20, 10);
            bodyList.Add(node1);
            var node2 = new NodePoint(nodePointRes);
            node2.RefreshPosition(21, 10);
            bodyList.Add(node2);
        }

        /// <summary>
        /// 向当前方向移动
        /// </summary>
        public void MoveForward()
        {
            LastDirection = curDirection;
            LastPointIndex.x = bodyList[bodyList.Count - 1].x;
            LastPointIndex.y = bodyList[bodyList.Count - 1].y;

            for (int i = bodyList.Count - 1; i > 0; i--)
            {
                bodyList[i].RefreshPosition(bodyList[i - 1].x, bodyList[i - 1].y);
            }

            bodyList[0].AddPosition(Mathf.FloorToInt(curDirection.x), Mathf.FloorToInt(curDirection.y));
        }

        /// <summary>
        /// 蛇蛇吃食物
        /// </summary>
        /// <param name="food">食物，也是组成蛇蛇身体的点</param>
        /// <returns>是否能吃得到食物</returns>
        public bool CheckEatFood(NodePoint food)
        {
            if (food.x == bodyList[0].x && food.y == bodyList[0].y)
            {
                food.RefreshPosition(LastPointIndex.x, LastPointIndex.y);
                bodyList.Add(food);
                return true;
            }

            return false;
        }

        /// <summary>
        /// 判断蛇蛇是否死亡，可以是撞墙和撞自己
        /// </summary>
        /// <returns></returns>
        public bool CheckIsDead()
        {
            //撞墙
            if (bodyList[0].x <= 0 || bodyList[0].x > Constant.MapWidth || bodyList[0].y > Constant.MapHeight ||
                bodyList[0].y <= 0)
            {
                return true;
            }

            //撞自己
            for (int i = 1; i < bodyList.Count; i++)
            {
                if (bodyList[0].x == bodyList[i].x && bodyList[0].y == bodyList[i].y)
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 重置蛇蛇到初始状态
        /// </summary>
        public void ResetSnake()
        {
            curDirection = Vector2.left;
            foreach (var node in bodyList)
            {
                node.OnDestroy();
            }

            bodyList.Clear();
            GnerateDefaultSnake();
        }

        /// <summary>
        /// 改变蛇蛇方向
        /// </summary>
        /// <param name="dir">需要改变成的方向</param>
        public void ChangeSnakeDirection(Vector2 dir)
        {
            if (dir == Vector2.up && LastDirection != Vector2.down)
            {
                curDirection = dir;
            }
            else if (dir == Vector2.down && LastDirection != Vector2.up)
            {
                curDirection = dir;
            }
            else if (dir == Vector2.left && LastDirection != Vector2.right)
            {
                curDirection = dir;
            }
            else if (dir == Vector2.right && LastDirection != Vector2.left)
            {
                curDirection = dir;
            }
        }
    }
}